package predict;

import codetree.*;
import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.Node;
import japa.parser.ast.body.*;
import japa.parser.ast.expr.VariableDeclarationExpr;
import japa.parser.ast.stmt.ExpressionStmt;
import treeview.DisplayTreeView;
import treeview.TreeView;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.*;
import java.io.*;

/**
 * Created by chenchi on 17/4/14.
 */
public class Predict implements Cloneable{
    private String serialNumberString;
    //private int holeNumber;
    public TreeNode childNode;
    public TreeNode parentNode;
    private boolean exchangeFlag = false;
    private boolean controlExchangeFlag = false;
    private int controlCount = 0;

    public void setChildNode(TreeNode childNode) {
        this.childNode = childNode;
    }

    public TreeNode getChildNode(){return childNode;}

    public String getSerialNumberString() {
        return serialNumberString;
    }

    public void setSerialNumberString(String serialNumberString) {
        this.serialNumberString = serialNumberString;
    }

    public Object clone()
    {
        Predict o=null;
        try
        {
            o=(Predict)super.clone();
        }
        catch(CloneNotSupportedException e)
        {
           // System.out.println(e.toString());
        }
        if(childNode != null) {
            o.childNode = (TreeNode) childNode.clone();
        }
        if(parentNode != null) {
            o.parentNode = (TreeNode) parentNode.clone();
        }
        return o;
    }


    public List<String> predict(CodeTree codeTree, String globalPath) {//String path
        CodeTreeOperation operation = new CodeTreeOperation();
        operation.setSerialNumberofEachNode(codeTree);
        //remove old hole node
        codeTree.removeHoleNode();
        //add new hole node
        TreeNode hole = new TreeNode();
        hole.setClassName("hole");
        hole.setCompleteClassName("hole");
        hole.setMethodName("");
        hole.setCompleteMethodName("");
        hole.setAddMethodName(false);
        hole.setSerialNumber(codeTree.getTotalNumber() + 1);
        //holeNumber = hole.getSerialNumber();
        codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), hole);
        operation.setSerialNumberofEachNode(codeTree);
       // if(codeTree.getHoleNode2() == null){
           // TreeView treeView = new TreeView();
           // treeView.convertCodeTree(codeTree,true);
           //DisplayTreeView displayTreeView = new DisplayTreeView(treeView.getTree(),"test");
       // }
       // serialNumberString = Integer.toString(codeTree.getHoleNode2().getParentNode().getSerialNumber());
        serialNumberString = "0";
        //save parameter in file
        List<Integer> list = operation.regularization(codeTree);
        String treeNumber = new String("");
        for (int i = 0; i < list.size(); i++) {
            treeNumber += list.get(i) + " ";
        }
        String treeSentence = operation.getTreeSentence(codeTree, true);
        //long start = System.currentTimeMillis();
        //File file = new File(globalPath + "/TreeLSTM/javaParameter/javaParameter.txt");
        /**start from here**/
//        File file = new File(globalPath + "/" + path);
//        try {
//            if(file.exists()){
//                file.delete();
//            }
//            if (!file.exists()) {
//                file.createNewFile();
//            }
//            //FileWriter writer = new FileWriter(globalPath + "/TreeLSTM/javaParameter/javaParameter.txt", true);
//            FileWriter writer = new FileWriter(globalPath + "/" + path, true);
//            writer.write(treeNumber + "\r\n");
//            writer.write(serialNumberString + "\r\n");
//            writer.write(treeSentence + "\r\n");
//            writer.close();
//        } catch (Exception e) {
//            System.err.println("file error");
//        }
        //long end = System.currentTimeMillis();
        // System.out.print("文件操作时间：");
        // System.out.println(end - start + "ms");
        /// long start2 = System.currentTimeMillis();
        Runtime run = Runtime.getRuntime();
        //String cmd = "lua " + globalPath + "/TreeLSTM/model/PredictResult.lua";
        //String cmd = "python " + globalPath + "/TreeLSTM/model/PredictResult.py";
        //String cmd = null;
//        if(path.endsWith("0.txt")){
//            cmd = "python " + globalPath + "/TreeLSTM/py/client0.py";
//        }else if(path.endsWith("1.txt")){
//            cmd = "python " + globalPath + "/TreeLSTM/py/client1.py";
//        }else if(path.endsWith("2.txt")){
//            cmd = "python " + globalPath + "/TreeLSTM/py/client2.py";
//        }else if(path.endsWith("3.txt")){
//            cmd = "python " + globalPath + "/TreeLSTM/py/client3.py";
//        }else if(path.endsWith("4.txt")){
//            cmd = "python " + globalPath + "/TreeLSTM/py/client4.py";
//        }
        //cmd = "python " + globalPath + "/TreeLSTM/py/client.py" + " " + treeNumber + " " + serialNumberString + " " + treeSentence;
        String[] cmd = new String[] {"python",globalPath + "/TreeLSTM/py/client.py",treeNumber,serialNumberString,treeSentence};
        List<String> top5Result = new ArrayList<>();
        try {
            Process p = run.exec(cmd);
            BufferedInputStream in = new BufferedInputStream(p.getInputStream());
            BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
            String line;
            boolean flag = false;
            while ((line = inBr.readLine()) != null) {
                if(line.equals("startrecord")){
                    flag = true;
                    continue;
                }
                if (flag) {
                    line = line.replaceAll("\r","");
                    line = line.replaceAll("\n","");
                    String prediciton = line.split(" +")[0];
                    //SyntaxChecker syntaxChecker = new SyntaxChecker();
                    //if(top5Result.size() < 5){
                    if(top5Result.size() < 10 && !prediciton.equals("conditionEnd") && !prediciton.equals("end") && !prediciton.equals("termination")){
                        top5Result.add(line);
                        //System.out.println(line);
                    }
                    /*
                    if(top5Result.size() < 10 && syntaxChecker.check(codeTree,Integer.parseInt(serialNumberString),line)){
                        top5Result.add(line);
                        System.out.println(line);
                    }*/
                }
            }
            //System.out.println();
        } catch (IOException e) {
           // System.err.println("python error");
        }
        //the following code is used to make sure that there are five candidates
        while(top5Result.size() < 5){
            top5Result.add("termination 0.01");
        }
        //String prediction = top5Result.get(0).split(" ")[0];
        //serialNumberString = operateCodeTree(codeTree, prediction);
        return top5Result;
    }

    public String predictTermination(CodeTree codeTree, String globalPath) {//String path
        CodeTreeOperation operation = new CodeTreeOperation();
        //remove old hole node
        codeTree.removeHoleNode();
        operation.setSerialNumberofEachNode(codeTree);
        List<Integer> list = operation.regularization(codeTree);
        String treeNumber = new String("");
        for (int i = 0; i < list.size(); i++) {
            treeNumber += list.get(i) + " ";
        }
        String treeSentence = operation.getTreeSentence(codeTree, true);
        Runtime run = Runtime.getRuntime();
        String[] cmd = new String[] {"python",globalPath + "/TreeLSTM/py/client.py",treeNumber,serialNumberString,treeSentence};
        List<String> top5Result = new ArrayList<>();
        try {
            Process p = run.exec(cmd);
            BufferedInputStream in = new BufferedInputStream(p.getInputStream());
            BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
            String line;
            boolean flag = false;
            while ((line = inBr.readLine()) != null) {
                if(line.equals("startrecord")){
                    flag = true;
                    continue;
                }
                if (flag) {
                    line = line.replaceAll("\r","");
                    line = line.replaceAll("\n","");
                    String prediciton = line.split(" +")[0];
                    if(top5Result.size() < 10){
                        top5Result.add(line);
                        //System.out.println(line);
                    }
                }
            }
            //System.out.println();
        } catch (IOException e) {
            //System.err.println("python error");
        }
        String result = top5Result.get(0);
        String[] strs = result.split(" +");
        if(strs[0].equals("termination") && Double.parseDouble(strs[1]) > 0.75 && Double.parseDouble(strs[1])<0.77){
            return "End";
        }else{
            return null;
        }
        //String prediction = top5Result.get(0).split(" ")[0];
        //serialNumberString = operateCodeTree(codeTree, prediction);
    }

    public String operateCodeTree(CodeTree codeTree, String prediction) {
        TreeNode predictNode = new TreeNode();
        predictNode.setCompleteMethodDeclaration(prediction);
        CodeTreeOperation operation = new CodeTreeOperation();
        operation.setSerialNumberofEachNode(codeTree);
        TreeNode node = codeTree.getTreeNode(Integer.parseInt(serialNumberString));
        if (prediction.equals("if") || prediction.equals("for")
                || prediction.equals("foreach") || prediction.equals("while") || prediction.equals("doWhile")
                || prediction.equals("try") || prediction.equals("switch")) {
            predictNode.setControl(true);
            controlExchangeFlag = true;
            controlCount++;
            if (childNode != null && controlCount == 1) {
                if(node.getChildNodes().contains(childNode)) {
                    node.getChildNodes().remove(childNode);
                    codeTree.addNode(predictNode, childNode);
                    codeTree.addNode(node, predictNode);
                }else{
                    codeTree.addNode(node, predictNode);
                }
            } else if (childNode != null && controlCount > 1) {
                if(node.getChildNodes().contains(childNode)) {
                    node.getChildNodes().remove(childNode);
                    codeTree.addNode(node, predictNode);
                    codeTree.addNode(node, childNode);
                }else{
                    codeTree.addNode(node, predictNode);
                }
            } else {
                codeTree.addNode(node, predictNode);
            }
            // codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
        } else if(prediction.equals("elseif") || prediction.equals("else")||prediction.equals("catch")||
                  prediction.equals("finally") || prediction.equals("case") || prediction.equals("default")){
            predictNode.setControl(true);
            if(childNode != null){
                TreeNode temp = childNode.getParentNode();
                temp.getChildNodes().remove(childNode);
                codeTree.addNode(temp, predictNode);
                codeTree.addNode(temp, childNode);
            }else {
                while(true){
                    if(node.getParentNode() != null){
                        if(node.getParentNode().isControl()){
                            codeTree.addNode(node.getParentNode(), predictNode);
                            break;
                        }else{
                            node = node.getParentNode();
                        }
                    }else{
                        break;
                    }
                }
            }
        } else if (prediction.equals("end")) {
            controlCount--;
            exchangeFlag = true;
            controlExchangeFlag = false;
            codeTree.addNode(node, predictNode);
        } else {
            if (childNode != null && !exchangeFlag) {
                if (node.getChildNodes().size() != 0 && !controlExchangeFlag) {
                    boolean flag = true;
                    for (int i = 0; i < node.getChildNodes().size(); i++) {
                        if (node.getChildNodes().get(i).equals(childNode)) {
                            node.getChildNodes().remove(i);
                            codeTree.addNode(predictNode, childNode);
                            codeTree.addNode(node, predictNode);
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        codeTree.addNode(node, predictNode);
                    }
                } else {
                    codeTree.addNode(node, predictNode);
                }
            } else if (childNode != null && exchangeFlag) {
                TreeNode temp = childNode.getParentNode();
                temp.getChildNodes().remove(childNode);
                codeTree.addNode(predictNode,childNode);
                codeTree.addNode(temp, predictNode);
                exchangeFlag = false;
            } else {
                codeTree.addNode(node, predictNode);
            }
        }
        serialNumberString = getSerialNumberString(codeTree, prediction, predictNode);
        //displayTree(codeTree, true);
        return serialNumberString;
    }

//    public String operateCodeTree(CodeTree codeTree, String prediction) {
//        TreeNode predictNode = new TreeNode();
//        TreeNode conditionNode = new TreeNode();
//        predictNode.setCompleteMethodDeclaration(prediction);
//        CodeTreeOperation operation = new CodeTreeOperation();
//        operation.setSerialNumberofEachNode(codeTree);
//        TreeNode node = codeTree.getTreeNode(Integer.parseInt(serialNumberString));
//        if (prediction.equals("if") || prediction.equals("for")
//                || prediction.equals("foreach") || prediction.equals("while") || prediction.equals("doWhile")
//                || prediction.equals("try") || prediction.equals("switch")) {
//            predictNode.setControl(true);
//            controlCount++;
//            if (prediction.equals("if") || prediction.equals("for")
//                    || prediction.equals("foreach") || prediction.equals("while") || prediction.equals("doWhile")
//                    || prediction.equals("switch")) {
//                prediction = "condition";
//                exchangeFlag = false;
//                conditionNode.setCompleteMethodDeclaration("condition");
//                codeTree.addNode(predictNode, conditionNode);
//            }
//            if (childNode != null && controlCount == 1) {
//                node.getChildNodes().remove(node.getChildNodes().size() - 1);
//                codeTree.addNode(predictNode, childNode);
//                codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
//            } else if (childNode != null && controlCount == 2) {
//                node.getChildNodes().remove(node.getChildNodes().size() - 1);
//                codeTree.addNode(node, predictNode);
//                codeTree.addNode(node, childNode);
//            } else {
//                codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
//            }
//            // codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
//        } else if (prediction.equals("end")) {
//
//            while (true) {
//                if (node.getCompleteMethodDeclaration().equals("condition")) {
//                    codeTree.addNode(node, predictNode);
//                    exchangeFlag = true;
//                    parentNode = node.getParentNode();
//                    break;
//                } else if (node.isControl()) {
//                    codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
//                    break;
//                } else {
//                    node = node.getParentNode();
//                }
//            }
//        } else {
//            if (childNode != null && !exchangeFlag) {
//                if (node.getChildNodes().size() != 0) {
//                    boolean flag = true;
//                    for (int i = 0; i < node.getChildNodes().size(); i++) {
//                        if (isEqual(node.getChildNodes().get(i), childNode, true)) {
//                            node.getChildNodes().remove(i);
//                            codeTree.addNode(predictNode, childNode);
//                            codeTree.addNode(node, predictNode);
//                            flag = false;
//                            break;
//                        }
//                    }
//                    if (flag) {
//                        codeTree.addNode(node, predictNode);
//                    }
//                } else {
//                    codeTree.addNode(node, predictNode);
//                }
//            } else if (childNode != null && exchangeFlag) {
//                codeTree.addNode(parentNode, predictNode);
//                int size = parentNode.getChildNodes().size();
//                TreeNode temp = parentNode.getChildNodes().get(size - 1);
//                parentNode.getChildNodes().set(size - 1, parentNode.getChildNodes().get(size - 2));
//                parentNode.getChildNodes().set(size - 2, temp);
//                exchangeFlag = false;
//            } else {
//                codeTree.addNode(codeTree.getTreeNode(Integer.parseInt(serialNumberString)), predictNode);
//            }
//        }
//
//        if (conditionNode.getCompleteMethodDeclaration().equals("condition")) {
//            serialNumberString = getSerialNumberString(codeTree, prediction, conditionNode);
//        } else {
//            serialNumberString = getSerialNumberString(codeTree, prediction, predictNode);
//        }
//        //displayTree(codeTree, true);
//        return serialNumberString;
//    }

    public String getSerialNumberString(CodeTree codeTree, String prediction, TreeNode predictNode) {
        CodeTreeOperation operation = new CodeTreeOperation();
        operation.setSerialNumberofEachNode(codeTree);
        if (prediction.equals("end") || prediction.equals("break") || prediction.equals("continue")){
                //|| prediction.equals("return")) {
            TreeNode currentNode = predictNode;
            while (true) {
                if (currentNode.getParentNode() != null) {
                    if (currentNode.getParentNode().isControl()){
                        serialNumberString = Integer.toString(currentNode.getParentNode().getSerialNumber());
                        break;
//                        if (currentNode.getParentNode().getChildNodes().get(0).getSerialNumber() == currentNode.getSerialNumber()) {
//                            serialNumberString = Integer.toString(currentNode.getParentNode().getSerialNumber());
//                            break;
//                        } else if (currentNode.getParentNode().getChildNodes().size() > 1 && currentNode.getParentNode().getChildNodes().get(1).getSerialNumber() == currentNode.getSerialNumber()) {
//                            serialNumberString = Integer.toString(currentNode.getParentNode().getSerialNumber());
//                            break;
//                        } else {
//                            currentNode = currentNode.getParentNode();
//                        }
                    } else {
                        currentNode = currentNode.getParentNode();
                    }
                } else {
                    break;
                }
            }
        }
        else if(prediction.equals("return")){
            TreeNode currentNode = predictNode;
            while (true) {
                if (currentNode.getParentNode() != null) {
                    if (currentNode.getParentNode().isControl()) {
                        if(currentNode.getParentNode().getChildNodes().indexOf(currentNode) == 0) {
                            serialNumberString = Integer.toString(currentNode.getParentNode().getSerialNumber());
                            break;
                        }else{
                            currentNode = currentNode.getParentNode();
                        }
                    }else{
                        currentNode = currentNode.getParentNode();
                    }
                }else{
                    break;
                }
            }
        }
        else {
            serialNumberString = Integer.toString(predictNode.getSerialNumber());
        }
        return serialNumberString;
    }

    public List<CodeTree> getCodeTree(String filePath, boolean isFilePath, boolean holeFlag, String globalPath, List<String> jdkList,List<String> gloveVocabList, List<String> stopWordsList) throws Exception {
        JapaAst japaAst = new JapaAst(true);
        List<String> tempList = new ArrayList<>();
        CompilationUnit cu = new CompilationUnit();
        try {
            if (isFilePath) {
                cu = JavaParser.parse(new File(filePath));
            } else {
                InputStream in = new ByteArrayInputStream(filePath.getBytes());
                cu = JavaParser.parse(in);
            }
            tempList = japaAst.parse(cu);
        } catch (Exception e) {
            List<CodeTree> result = new ArrayList<>();
            result.add(null);
            return result;
        } catch (Error e) {
            List<CodeTree> result = new ArrayList<>();
            result.add(null);
            return result;
        }
        //如果Import的包中带有*号，那么得到含有*号的这个import
        List importList = cu.getImports();
        List<String> starImportStringList = new ArrayList<>();
        if (importList != null) {
            for (int i = 0; i < importList.size(); i++) {
                if (importList.get(i).toString().contains("*")) {
                    String str = importList.get(i).toString();
                    int index = str.indexOf("import");
                    str = str.substring(index);
                    String[] strs = str.split(" ");
                    str = strs[strs.length - 1];//得到Import的包的信息
                    str = str.replace(" ", ""); //替换掉空格" "
                    str = str.replace(";", ""); //去除;
                    starImportStringList.add(str);
                }
            }
        }
        //开始分析程序
        List<CodeTree> result = new ArrayList<>();
        if (cu.getTypes() != null) {
            for (TypeDeclaration type : cu.getTypes()) {
                if (type instanceof ClassOrInterfaceDeclaration) {
                    //处理field
                    List<VariableDeclarationExpr> fieldExpressionList = new ArrayList<>();
                    for (BodyDeclaration body : type.getMembers()) {
                        if (body instanceof FieldDeclaration) {
                            FieldDeclaration field = (FieldDeclaration) body;
                            for (int i = 0; i < field.getVariables().size(); i++) {
                                VariableDeclarationExpr expr = new VariableDeclarationExpr();
                                List list = new ArrayList();
                                list.add(field.getVariables().get(i));
                                expr.setType(field.getType());
                                expr.setVars(list);
                                fieldExpressionList.add(expr);
                            }
                        }
                    }
                    //处理method
                    for (BodyDeclaration body : type.getMembers()) {
                        if (body instanceof MethodDeclaration || body instanceof ConstructorDeclaration) {
                            if ((body.getEndLine() - body.getBeginLine() <= 826)) {
                                List<String> completeClassNameList = new ArrayList<>();
                                for (String str : tempList) {
                                    completeClassNameList.add(str);
                                }
                                List userClassList = new ArrayList();
                                for (String str : japaAst.getFilternames()) {
                                    userClassList.add(str);
                                }
                                UserClassProcessing userClassProcessing = new UserClassProcessing();
                                userClassProcessing.setUserClassList(userClassList);
                                userClassProcessing.setJdkList(jdkList);
                                userClassList.add("userDefinedClass");
                                MethodDeclaration method;
                                if(body instanceof ConstructorDeclaration){
                                    String constructorDeclaration = body.toString();
                                    String str = constructorDeclaration.split("\\(")[0];
                                    String str2 = str;
                                    String[] strs = str2.split(" +");
                                    String str3 = "";
                                    for(int i = 0; i < strs.length - 1; i ++){
                                        str3 += strs[i];
                                        str3 += " ";
                                    }
                                    str3 += "void ";
                                    str3 += strs[strs.length - 1].toLowerCase();
                                    constructorDeclaration = constructorDeclaration.replaceFirst(str,str3);
                                    constructorDeclaration = "public class Test{" + constructorDeclaration + "}";
                                    InputStream in = new ByteArrayInputStream(constructorDeclaration.getBytes());
                                    try {
                                        CompilationUnit compilationUnit = JavaParser.parse(in);
                                        method = (MethodDeclaration) compilationUnit.getTypes().get(0).getMembers().get(0);
                                        method.setBody(((ConstructorDeclaration) body).getBlock());
                                    } catch (Exception e) {
                                        result.add(null);
                                        return result;
                                        //continue;
                                    } catch (Error e) {
                                        result.add(null);
                                        return result;
                                        //continue;
                                    }
                                }else{
                                    method = (MethodDeclaration) body;
                                }
                                //MethodDeclaration method = (MethodDeclaration) body;
                                List<String> parameterNameList = new ArrayList<>();
                                List<String> typeMapList = new ArrayList<>();
                                List<String> completeTypeMapList = new ArrayList<>();
                                List<ExpressionStmt> parameterExpressionList = new ArrayList<>();
                                if (method.getParameters() != null) {
                                    List<Parameter> parameterList = method.getParameters();
                                    for (int i = 0; i < parameterList.size(); i++) {
                                        String contentString = "public class Test{public void test(){$}}";
                                        String parameterString = parameterList.get(i).toString() + ";";
                                        contentString = contentString.replaceAll("\\$", parameterString);
                                        InputStream in = new ByteArrayInputStream(contentString.getBytes());
                                        try {
                                            CompilationUnit compilationUnit = JavaParser.parse(in);
                                            Node node = compilationUnit.getTypes().get(0).getMembers().get(0);
                                            ExpressionStmt expression = (ExpressionStmt) node.getChildrenNodes().get(1).getChildrenNodes().get(0);
                                            parameterExpressionList.add(expression);
                                        } catch (Exception e) {
                                            //result.add(null);
                                            //return result;
                                            continue;
                                        } catch (Error e) {
                                            //result.add(null);
                                            //return result;
                                            continue;
                                        }
                                    }
                                }
                                /*添加类中的成员变量*/
                                SimplifiedTreeCreator creator = new SimplifiedTreeCreator(globalPath);
                                creator.setUserClassProcessing(userClassProcessing);
                                creator.setStarImportStringList(starImportStringList);
                                List<String> tempUserClassList = new ArrayList<>();
                                for (int i = 0; i < completeClassNameList.size(); i++) {
                                    try {
                                        Class clazz = Thread.currentThread().getContextClassLoader().loadClass(completeClassNameList.get(i));
                                        if(jdkList.contains(completeClassNameList.get(i))){
                                            creator.getClass_name_map().put(clazz.getSimpleName(), completeClassNameList.get(i));
                                        }else{
                                            tempUserClassList.add(completeClassNameList.get(i));
                                            userClassList.add(completeClassNameList.get(i));
                                        }
                                    } catch (Exception e) {
                                        tempUserClassList.add(completeClassNameList.get(i));
                                        userClassList.add(completeClassNameList.get(i));
                                    } catch (Error e) {
                                        //System.err.println(e.getCause());
                                        tempUserClassList.add(completeClassNameList.get(i));
                                        userClassList.add(completeClassNameList.get(i));
                                    }

                                }
                                //过滤掉反射不到的类
                                for (int i = 0; i < tempUserClassList.size(); i++) {
                                    completeClassNameList.remove(tempUserClassList.get(i));
                                }
                                tempUserClassList.removeAll(tempUserClassList);
                                //处理field
                                for (int i = 0; i < fieldExpressionList.size(); i++) {
                                    creator.convert(fieldExpressionList.get(i));
                                }
                                //处理method中的parameter
                                for (int i = 0; i < parameterExpressionList.size(); i++) {
                                    creator.convert(parameterExpressionList.get(i));
                                }
                    /*get code tree from japa parse*/
                                CodeTree codeTree = constructTreeFromAST(completeClassNameList, parameterNameList, typeMapList,
                                        completeTypeMapList, starImportStringList, method, creator, userClassProcessing, holeFlag, globalPath,jdkList,gloveVocabList,stopWordsList);
                                if (codeTree != null) {
 //                                   System.out.println(1111);
 //                                     displayTree(codeTree, true, method.getName() + (method.getParameters() == null ? "[]" : method.getParameters()));

//                                    codeTree.setClass_name_map(creator.getClass_name_map());
//                                    codeTree.setClass_variable(creator.getClass_variable());
//                                    codeTree.setClass_variable_list(creator.getClass_variable_list());
//                                    codeTree.setVariable_use_map(creator.getVariable_use_map());
//                                    codeTree.setVariable_line_map(creator.getVariable_line_map());
                                    result.add(codeTree);
                                } else {
                                    result.add(null);
                                    //System.err.println("So " + method.getName() + (method.getParameters() == null ? "[]" : method.getParameters()) + " (" + filePath + ") " + " can not be correctly parsed");
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

//    public List<CodeTree> getCodeTree2(String filePath, boolean isFilePath, boolean holeFlag, String globalPath) throws Exception {
//        List<String> completeClassNameList = new ArrayList<>();
//        JdtAst jdtAst = new JdtAst(true);
//        completeClassNameList = jdtAst.parse(filePath, isFilePath);
//        List userClassList = jdtAst.getFilternames();
//        UserClassProcessing userClassProcessing = new UserClassProcessing();
//        userClassProcessing.setUserClassList(userClassList);
//        userClassList.add("userDefinedClass");
//        CompilationUnit cu = new CompilationUnit();
//        if (isFilePath) {
//            cu = JavaParser.parse(new File(filePath));
//        } else {
//            InputStream in = new ByteArrayInputStream(filePath.getBytes());
//            cu = JavaParser.parse(in);
//        }
//        //如果Import的包中带有*号，那么得到含有*号的这个import
//        List importList = cu.getImports();
//        List<String> starImportStringList = new ArrayList<>();
//        for (int i = 0; i < importList.size(); i++) {
//            if (importList.get(i).toString().contains("*")) {
//                String str = importList.get(i).toString();
//                int index = str.indexOf("import");
//                str = str.substring(index);
//                String[] strs = str.split(" ");
//                str = strs[strs.length - 1];//得到Import的包的信息
//                str = str.replace(" ", ""); //替换掉空格" "
//                str = str.replace(";", ""); //去除;
//                starImportStringList.add(str);
//            }
//        }
//        //开始分析程序
//        List<CodeTree> result = new ArrayList<>();
//        for (TypeDeclaration type : cu.getTypes()) {
//            //处理field
//            List<VariableDeclarationExpr> fieldExpressionList = new ArrayList<>();
//            for (BodyDeclaration body : type.getMembers()) {
//                if (body instanceof FieldDeclaration) {
//                    FieldDeclaration field = (FieldDeclaration) body;
//                    for (int i = 0; i < field.getVariables().size(); i++) {
//                        VariableDeclarationExpr expr = new VariableDeclarationExpr();
//                        List list = new ArrayList();
//                        list.add(field.getVariables().get(i));
//                        expr.setType(field.getType());
//                        expr.setVars(list);
//                        fieldExpressionList.add(expr);
//                    }
//                }
//            }
//            //处理method
//            for (BodyDeclaration body : type.getMembers()) {
//                if (body instanceof MethodDeclaration) {
//                    MethodDeclaration method = (MethodDeclaration) body;
//                    List<String> parameterNameList = new ArrayList<>();
//                    List<String> typeMapList = new ArrayList<>();
//                    List<String> completeTypeMapList = new ArrayList<>();
//                    if (method.getParameters() != null) {
//                        List<Parameter> parameterList = method.getParameters();
//                        for (int i = 0; i < parameterList.size(); i++) {
//                            String[] strings = parameterList.get(i).toString().split(" ");
//                            parameterNameList.add(strings[strings.length - 1]);
//                            typeMapList.add(strings[strings.length - 1] + " " + parameterList.get(i).getType().toString());
//                            completeTypeMapList.add(parameterList.get(i).getType().toString());
//                        }
//                    }
//                    /*添加类中的成员变量*/
//                    SimplifiedTreeCreator creator = new SimplifiedTreeCreator(globalPath);
//                    creator.setUserClassProcessing(userClassProcessing);
//                    creator.setStarImportStringList(starImportStringList);
//                    for (int i = 0; i < completeClassNameList.size(); i++) {
//                        try {
//                            Class clazz = Thread.currentThread().getContextClassLoader().loadClass(completeClassNameList.get(i));
//                            creator.getClass_name_map().put(clazz.getSimpleName(), completeClassNameList.get(i));
//                        } catch (ClassNotFoundException e) {
//                            e.printStackTrace();
//                        }
//
//                    }
//                    for (int i = 0; i < fieldExpressionList.size(); i++) {
//                        creator.convert(fieldExpressionList.get(i));
//                    }
//                    /*get code tree from japa parse*/
//                    CodeTree codeTree = constructTreeFromAST(completeClassNameList, parameterNameList, typeMapList,
//                            completeTypeMapList, starImportStringList, method, creator, userClassProcessing, holeFlag, globalPath,jdkList);
//                    if (codeTree != null) {
//                        codeTree.setClass_name_map(creator.getClass_name_map());
//                        codeTree.setClass_variable(creator.getClass_variable());
//                        codeTree.setClass_variable_list(creator.getClass_variable_list());
//                        codeTree.setVariable_use_map(creator.getVariable_use_map());
//                        codeTree.setVariable_line_map(creator.getVariable_line_map());
//                        result.add(codeTree);
//                    } else {
//                        System.err.println("So " + method.getName() + (method.getParameters() == null ? "[]" : method.getParameters()) + " (" + filePath + ") " + " can not be correctly parsed");
//                    }
//
//                }
//            }
//        }
//        return result;
//    }

    public CodeTree constructTreeFromAST(List<String> completeClassNameList, List<String> parameterNameList,
                                         List<String> typeMapList, List<String> completeTypeMapList,
                                         List<String> starImportStringList, MethodDeclaration method,
                                         SimplifiedTreeCreator fieldCreator, UserClassProcessing userClassProcessing,
                                         boolean holeFlag, String globalPath, List<String> jdkList,
                                         List<String> gloveVocabList, List<String> stopWordsList ) {
        try {
            SimplifiedTreeCreator creator = new SimplifiedTreeCreator(completeClassNameList, fieldCreator, globalPath, jdkList);
            creator.setHoleFlag(holeFlag);
            for (int i = 0; i < parameterNameList.size(); i++) {
                creator.addClass_variable_list(parameterNameList.get(i));
            }
            for (int i = 0; i < typeMapList.size(); i++) {
                String[] strings = typeMapList.get(i).split(" ");
                creator.addClass_variable(strings[0], strings[1]);
            }
            for (int i = 0; i < completeTypeMapList.size(); i++) {
                creator.addClass_name_map(completeTypeMapList.get(i));
            }
            creator.setStarImportStringList(starImportStringList);
            creator.setUserClassProcessing(userClassProcessing);
            creator.toCodeTree(method);
            CodeTree codeTree = new CodeTree();
            codeTree.setRoot(creator.getCodeTree().getRoot());
            if(creator.getParsedFlag() && codeTree.getRoot() != null) {
                //移除没有用到的变量声明结点
                /*
                Map<String, List<TreeNode>> map = creator.getVariableNodeMap();
                for (String key : map.keySet()) {
                    List<TreeNode> list = map.get(key);
                    for (int i = 0; i < list.size(); i++) {
                        if ((list.get(i).isVariableDeclaration() && list.get(i).isPrimitive() && !list.get(i).isVariablePreserved() && list.get(i).isUsed())
                                || list.get(i).isAssign()) {
                            if (!codeTree.removeNode(list.get(i))) {
                                return null;
                            }
                        }
                    }
                }*/
                //添加类属性变量和函数声明中的变量
//                codeTree.getRoot().setPreviousVariableNames(creator.getUsedClassFieldAndMethodArgumentVariable());
//                if (codeTree.getRoot().getPreviousVariableNames() != null) {
//                    for (int i = 0; i < codeTree.getRoot().getPreviousVariableNames().size(); i++) {
//                        String variableName = codeTree.getRoot().getPreviousVariableNames().get(i);
//                        variableName = variableName.replaceAll("\r", "");
//                        variableName = variableName.replaceAll("\n", "");
//                        codeTree.getRoot().getPreviousVariableNames().set(i, variableName);
//                    }
//                }
                //加入变量名
//                codeTree.processRootVariables(codeTree.getRoot(), gloveVocabList, stopWordsList);
//                List<String> duplicatedVariableList = new ArrayList<>();
//                codeTree.initPreviousVariables(codeTree.getRoot(), duplicatedVariableList, gloveVocabList, stopWordsList);
                //加入注释
                //codeTree.initCommentList(codeTree.getRoot(), creator.getCommentList());
                //过滤掉原始语句中的\r\n符号
                //codeTree.filterSpecialCharacterInOriginalStatement(codeTree.getRoot());
                codeTree.setClass_name_map(creator.getClass_name_map());
                codeTree.setClass_variable(creator.getClass_variable());
                codeTree.setClass_variable_list(creator.getClass_variable_list());
                codeTree.setVariable_use_map(creator.getVariable_use_map());
                codeTree.setVariable_line_map(creator.getVariable_line_map());
                return codeTree;
            }
            else {
                return null;
            }
        } catch (Exception e) {
            return null;
        } catch (Error e) {
            return null;
        }
    }

//    public CodeTree constructTreeFromAST2(List<String> completeClassNameList, List<String> parameterNameList,
//                                         List<String> typeMapList, List<String> completeTypeMapList,
//                                         List<String> starImportStringList, MethodDeclaration method,
//                                         SimplifiedTreeCreator fieldCreator, UserClassProcessing userClassProcessing,
//                                         boolean holeFlag, String globalPath,List<String> jdkList) {
//        SimplifiedTreeCreator creator = new SimplifiedTreeCreator(completeClassNameList, fieldCreator, globalPath,jdkList);
//        creator.setHoleFlag(holeFlag);
//        for (int i = 0; i < parameterNameList.size(); i++) {
//            creator.addClass_variable_list(parameterNameList.get(i));
//        }
//        for (int i = 0; i < typeMapList.size(); i++) {
//            String[] strings = typeMapList.get(i).split(" ");
//            creator.addClass_variable(strings[0], strings[1]);
//        }
//        for (int i = 0; i < completeTypeMapList.size(); i++) {
//            creator.addClass_name_map(completeTypeMapList.get(i));
//        }
//        creator.setStarImportStringList(starImportStringList);
//        creator.setUserClassProcessing(userClassProcessing);
//        creator.toCodeTree(method);
//        CodeTree codeTree = new CodeTree();
//        codeTree.setRoot(creator.getCodeTree().getRoot());
//        if (creator.getParsedFlag()) {
//            return codeTree;
//        } else {
//            return null;
//        }
//    }

    public boolean isEqual(TreeNode node, TreeNode comparedNode, boolean flag) {
        boolean result = flag;
        if (!node.getCompleteMethodDeclaration().equals(comparedNode.getCompleteMethodDeclaration())
                || node.getChildNodes().size() != comparedNode.getChildNodes().size()) {
            result = false;
        } else {
            for (int i = 0; i < node.getChildNodes().size(); i++) {
                if (node.getChildNodes().get(i).getCompleteMethodDeclaration().equals(comparedNode.getChildNodes().get(i).getCompleteMethodDeclaration())) {
                    result = isEqual(node.getChildNodes().get(i), comparedNode.getChildNodes().get(i), result);
                } else {
                    result = false;
                    break;
                }
            }
        }
        return result;
    }

    public void displayTree(CodeTree codeTree, boolean isCompleteFlag, String title) {
        TreeView treeView = new TreeView();
        treeView.convertCodeTree(codeTree, isCompleteFlag);
        DisplayTreeView display = new DisplayTreeView(treeView.getTree(), title);

    }
}
